/********************************************************************
# Copyright 2018-2019 Daniel 'grindhold' Brendle
#
# This file is part of libphexfile.
#
# libphexfile is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later
# version.
#
# libphexfile is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with libphexfile.
# If not, see http://www.gnu.org/licenses/.
*********************************************************************/

using Phexfile;

namespace PhexfileTest {
    class Main {
        public static int main(string[] argv) {
            Test.init(ref argv);
            FormatTest.add_tests();
            Test.run();
            return 0;
        }
    }

    class FormatTest {
        public static void add_tests() {
            Test.add_func("/phexfile/10x10", () => {
                Simulation sim = null;
                try {
                    sim = Simulation.load_from_json(FIXTURE_10X10);
                } catch (PhexfileError e) {
                    Test.fail();
                }

                assert(sim.title == "Testsimulation");
                assert(sim.description == "Some desecriptive Text");

                assert(sim.get_excitations().length() == 3);
                assert(sim.get_methods().length() == 4);
                assert(sim.get_coordinates().length() == 2);

                assert(sim.get_error_at({9,9}) == "Could not converge");

                try {
                    assert(sim.get_energy_fixed({0,1}, "cc-eom/sto-3g","S0") == 1.01d);
                    assert(sim.get_energy_fixed({1,0}, "cc-eom/aug-cc-pvdz","S0") == 4.1);
                    assert(sim.get_energy_fixed({1,0}, "scf/sto-3g","S0") == 7.1);
                    assert(sim.get_energy_fixed({1,0}, "scf/sto-3g","T1") == 9.1);
                    assert(sim.get_energy_fixed({1,0}, "scf/aug-cc-pvdz","S0") == 10.1);
                } catch (PhexfileError e) {
                    Test.fail();
                }

                double[] plot = null;
                try {
                    plot = sim.get_energies( {Simulation.X_AXIS, Simulation.Y_AXIS}, "cc-eom/sto-3g");
                } catch (PhexfileError e) {
                    Test.fail();
                }

                for (int k = 0; k < 3; k++) {
                    for (int i = 0; i < 10; i++ ) {
                        for (int j = 0; j < 10; j++ ) {
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[0] == (k+1).to_string()[0]);
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[2] == i.to_string()[0]);
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[3] == j.to_string()[0]);
                        }
                    }
                }

                string geom = """3
foo
 H  0.0  0.01 0.0
 O  0.0  0.0  0.0
 H  0.0  0.01  0.0""";
                assert(sim.get_geometry_xyz({0,1}) == geom);

                Atom?[] atoms = sim.get_geometry_struct({0,1});

                assert (atoms[0].atom == "H");
                assert (atoms[0].x == 0.0d);
                assert (atoms[0].y == 0.01d);
                assert (atoms[0].z == 0.0d);

                assert (atoms[1].atom == "O");
                assert (atoms[1].x == 0.0d);
                assert (atoms[1].y == 0.0d);
                assert (atoms[1].z == 0.0d);

                assert (atoms[2].atom == "H");
                assert (atoms[2].x == 0.0d);
                assert (atoms[2].y == 0.01d);
                assert (atoms[2].z == 0.0d);
            });

            Test.add_func("/phexfile/10x10x10", () => {
                Simulation sim = null;
                try {
                    sim = Simulation.load_from_json(FIXTURE_10X10X10);
                } catch (PhexfileError e) {
                    Test.fail();
                }

                assert(sim.title == "Testsimulation");
                assert(sim.description == "Some desecriptive Text");

                assert(sim.get_excitations().length() == 3);
                assert(sim.get_methods().length() == 4);
                assert(sim.get_coordinates().length() == 3);

                assert(sim.get_error_at({9,9}) == "");

                try {
                    assert("%f".printf(sim.get_energy_fixed({2,0,1}, "cc-eom/sto-3g","S0")) == "1.201000");
                    assert(sim.get_energy_fixed({2,1,0}, "cc-eom/aug-cc-pvdz","S0") == 4.21 );
                    assert(sim.get_energy_fixed({2,1,0}, "scf/sto-3g","S0") == 7.21);
                    assert("%f".printf(sim.get_energy_fixed({2,1,0}, "scf/sto-3g","T1")) == "9.210000");
                    assert("%f".printf(sim.get_energy_fixed({2,1,0}, "scf/aug-cc-pvdz","S0")) == "10.210000");
                } catch (PhexfileError e) {
                    Test.fail();
                }

                double[] plot = null;
                try {
                    plot = sim.get_energies( {2, Simulation.X_AXIS, Simulation.Y_AXIS}, "cc-eom/sto-3g");
                } catch (PhexfileError e) {
                    Test.fail();
                }

                for (int k = 0; k < 3; k++) {
                    for (int i = 0; i < 10; i++ ) {
                        for (int j = 0; j < 10; j++ ) {
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[0] == (k+1).to_string()[0]);
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[2] == '2');
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[3] == i.to_string()[0]);
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[4] == j.to_string()[0]);
                        }
                    }
                }

                plot = null;
                try {
                    plot = sim.get_energies( {Simulation.X_AXIS, Simulation.Y_AXIS, 2}, "cc-eom/sto-3g");
                } catch (PhexfileError e) {
                    Test.fail();
                }

                for (int k = 0; k < 3; k++) {
                    for (int i = 0; i < 10; i++ ) {
                        for (int j = 0; j < 10; j++ ) {
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[0] == (k+1).to_string()[0]);
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[2] == i.to_string()[0]);
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[3] == j.to_string()[0]);
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[4] == '2');
                        }
                    }
                }

                plot = null;
                try {
                    plot = sim.get_energies( {Simulation.Y_AXIS, 2,Simulation.X_AXIS}, "cc-eom/sto-3g");
                } catch (PhexfileError e) {
                    Test.fail();
                }

                for (int k = 0; k < 3; k++) {
                    for (int i = 0; i < 10; i++ ) {
                        for (int j = 0; j < 10; j++ ) {
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[0] == (k+1).to_string()[0]);
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[2] == j.to_string()[0]);
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[3] == '2');
                            assert(("%f".printf(plot[i*10*3+j*3+k]))[4] == i.to_string()[0]);
                        }
                    }
                }
            });
        }
    }
}
